import geom.Solid;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.FileNotFoundException;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.TransformGroup;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JSplitPane;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;


import com.sun.j3d.loaders.IncorrectFormatException;
import com.sun.j3d.loaders.ParsingErrorException;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.universe.SimpleUniverse;

/*
 * Created on Oct 19, 2006
 * 
 * $Id: SolidDisplay.java Feb 8, 2004 izpack-frontend
 * Copyright (C) 2005 Andy Gombos
 * 
 * File : SolidDisplay.java 
 * Description : TODO Add description
 * Author's email : gumbo@users.berlios.de
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class SolidDisplay extends JFrame implements AdjustmentListener
{

    /**
     * Simple Java 3D example program to display a spinning cube.
     */

    private TransformGroup sceneView = new TransformGroup();
    private TransformGroup sceneSlice = new TransformGroup();
    
    Solid slicePlane;
    double zSize;
    ModelTest mt;
    
    BranchGroup sliceGrp;
    
    double prevZoom;
    
    SimpleUniverse univ1 , univ2;

    public void createSceneGraph(boolean makingSliceScene)
    {
        // Create the root of the branch graph
        BranchGroup objRoot = new BranchGroup();       
        
        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
                        1000.0);
        
        // Create the TransformGroup node and initialize it to the
        // identity. Enable the TRANSFORM_WRITE capability so that
        // our behavior code can modify it at run time. Add it to
        // the root of the subgraph.
        TransformGroup objTrans = makingSliceScene ? sceneSlice : sceneView;
        
        System.out.println(objTrans);
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objRoot.addChild(objTrans);

        // Create a simple Shape3D node; add it to the scene graph.
                     
        Color3f alColour = new Color3f(0.4f, 0.4f, 0.4f);
        Color3f t = new Color3f();
        AmbientLight aLgt = new AmbientLight(alColour);
        aLgt.setInfluencingBounds(bounds);
        DirectionalLight dl = new DirectionalLight();
        dl.setInfluencingBounds(bounds);
        dl.getColor(t);
        System.out.println(t);
        DirectionalLight dl2 = new DirectionalLight(t, new Vector3f(1, 1, 0));
        dl2.setInfluencingBounds(bounds);
        
        objRoot.addChild(aLgt);
        objRoot.addChild(dl);
        objRoot.addChild(dl2);

        // Create a new Behavior object that will perform the
        // desired operation on the specified transform and add
        // it into the scene graph.
        /*Transform3D yAxis = new Transform3D();
        Alpha rotationAlpha = new Alpha(-1, 4000);

        RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
                        objTrans, yAxis, 0.0f, (float) Math.PI * 2.0f);
        rotator.setSchedulingBounds(bounds);
        objRoot.addChild(rotator);*/

        // Have Java 3D perform optimizations on this scene graph.
        //objRoot.compile();
        
        if (makingSliceScene)
        	univ2.addBranchGraph(objRoot);
        else
        	univ1.addBranchGraph(objRoot);
    }

    private Canvas3D createUniverse(boolean makingSliceScene)
    {
        // Get the preferred graphics configuration for the default screen
        GraphicsConfiguration config = SimpleUniverse
                        .getPreferredConfiguration();

        // Create a Canvas3D using the preferred configuration
        Canvas3D c = new Canvas3D(config);
        
        SimpleUniverse univ;
        
        if (makingSliceScene)
        	univ = univ2 = new SimpleUniverse(c);        
        else
        	univ = univ1 = new SimpleUniverse(c);
        
        // Create simple universe with view branch        

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        univ.getViewingPlatform().setNominalViewingTransform();
        
        OrbitBehavior orbit = new OrbitBehavior(c);
        orbit.setSchedulingBounds(new BoundingSphere(new Point3d(0, 0, 0), 1000));
        
        univ.getViewingPlatform().setViewPlatformBehavior(orbit);

        // Ensure at least 5 msec per frame (i.e., < 200Hz)
        univ.getViewer().getView().setMinimumFrameCycleTime(5);

        return c;
    }

    public SolidDisplay() throws FileNotFoundException, IncorrectFormatException, ParsingErrorException
    {   
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        
        JScrollBar zChanger = new JScrollBar(JScrollBar.VERTICAL);
        JSplitPane views = new JSplitPane();
        
        views.setDividerLocation(100);
        views.setContinuousLayout(true);
        
              
        setLayout(new BorderLayout());
        getContentPane().add(views, BorderLayout.CENTER);
        getContentPane().add(zChanger, BorderLayout.EAST);
        
        zChanger.addAdjustmentListener(this);
        
        // Create Canvas3D and SimpleUniverse; add canvas to drawing panel
        Canvas3D c1 = createUniverse(false);
        Canvas3D c2 = createUniverse(true);
        
        c2.setMaximumSize(new Dimension(0,0));
        c2.setMinimumSize(new Dimension(0,0));
        
        views.setLeftComponent(c1);
        views.setRightComponent(c2);
        
        mt = new ModelTest();
        Solid s = mt.getObj();
        slicePlane = mt.getBox();        
                     
        BoundingBox size = (BoundingBox) s.getBounds();
        
        Point3d upper = new Point3d(), lower = new Point3d();
        size.getUpper(upper);
        size.getLower(lower);
        
        zSize = Math.abs(upper.z - lower.z);
        
        sceneSlice.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        sceneSlice.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
        sceneSlice.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
        
        sceneView.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        sceneView.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
        sceneView.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
        
               
             // Create the content branch and add it to the universe
        createSceneGraph(true);
        createSceneGraph(false);
                     
        BranchGroup bg = new BranchGroup();
        bg.addChild(s);
        bg.addChild(slicePlane);
        sceneView.addChild(bg);
                
        sliceGrp = new BranchGroup();
        sliceGrp.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        sliceGrp.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
        sliceGrp.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        sliceGrp.setCapability(BranchGroup.ALLOW_DETACH);
        sliceGrp.addChild(mt.getChunk(slicePlane));
        sceneSlice.addChild(sliceGrp);      
        
        setPreferredSize(new Dimension(500, 500));
        pack();
        setVisible(true);
    }
    
    public static void main(String[] args) throws FileNotFoundException, IncorrectFormatException, ParsingErrorException
    {
        new SolidDisplay();
    }

	public void adjustmentValueChanged(AdjustmentEvent arg0) {
		if (!arg0.getValueIsAdjusting())
		{
			double dist = zSize / 100.0 * arg0.getValue();		
					
			slicePlane.zoom(dist - prevZoom);
			
			prevZoom = dist;
			
			Solid chunk = mt.getChunk(slicePlane);
			
			
			
			sliceGrp.detach();
			sliceGrp.setChild(chunk, 0);
			sceneSlice.addChild(sliceGrp);
		}
		
	}
	
	SliceDisplay pd;
}
